---------------------------------------------------------------
-- 英雄逻辑

-- addHero 				根据英雄id添加英雄
-- addHeroByGrid 		根据英雄grid添加英雄（注意grid没有被其它地方引用）
-- delHeroByIndex 		根据英雄下表删除英雄
---------------------------------------------------------------

local HeroExcel = require("excel.hero")
local UpNeedExcel = require("excel.upNeed")
local TequanExcel = require("excel.qqTequan")
local SkillExcel = require("excel.skill")
local BufferExcel = require("excel.buffer")
local SkinExcel = require("excel.skin")
local EquipExcel = require("excel.equip")
local Log = require("common.Log")
local LogDefine = require("common.LogDefine")
local Lang = require("common.Lang")
local Util = require("common.Util")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local Broadcast = require("broadcast.Broadcast")
local BarTaskLogic = require("bar.BarTaskLogic")
local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
local RoleAttr = require("role.RoleAttr")
local RoleDefine = require("role.RoleDefine")
local RoleHeadLogic = require("role.RoleHeadLogic")
local RoleDBLogic = require("role.RoleDBLogic")
local HeroBook = require("hero.HeroBook")
local HeroGrid = require("hero.HeroGrid")
local HeroDefine = require("hero.HeroDefine")
local HeroEquip = require("hero.HeroEquip")
local CombatPosLogic = require("combat.CombatPosLogic")
local CombatDefine = require("combat.CombatDefine")
local SkinLogic = require("skin.SkinLogic")
local FenjieLogic = require("hecheng.FenjieLogic")
local MonthHecJuex = require("monthAct.MonthHecJuex")
local JjcLogic = require("jjc.JjcLogic")
local HechengLogic = require("hecheng.HechengLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local GuideLogic = require("guide.GuideLogic")
local RoleLogic = require("role.RoleLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local TuiSongLiBao = require("present.TuiSongLiBao")
local SuipianLogic = require("bag.SuipianLogic")
local MoshouLogic = require("moshou.MoshouLogic")
local LiLianLogic = require("dailyTask.LiLianLogic")
local VipLogic = require("vip.VipLogic")
local FuwenLogic = require("fuwen.FuwenLogic")
local GlobalWorld = require("core.GlobalWorld")
local SysParameter = require("common.SysParameter")
local JibanLogic = require("combat.JibanLogic")
local HeroLogic = require("hero.HeroLogic")
local EquipLogic = require("equip.EquipLogic")
local XingYaoGongMing = require("xingYaoMen.XingYaoGongMing")
local HeroGrowUp = require("absAct.HeroGrowUp")
local MengxinLogic = require("present.MengxinLogic")
local Config = require("Config")
local HeroLogLogic = require("absAct.HeroLogLogic")
local ExclusiveTaskLogic = require("absAct.ExclusiveTaskLogic")
local BingshuLogic = require("fuwen.BingshuLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local BingshuLogic = require("fuwen.BingshuLogic")

HERO_MAX_STAR    =        15    -- 目前英雄最大星级

local HERO_RESET_FREECNT = 3 	-- 每日重置次数	
local HERO_RESET_MAXSTAR = 9 	-- 只能重置9星以下(包含9星)	
local CHONGSHENG_RETURN_STAR = 5 -- 重生返还x星本体碎片	

----------------------------------- 结构体封装 --------------------------------------
-- 获取技能信息
function makeSkillNet(net, id)
	local skillConfig = SkillExcel.skill[id]
	if not skillConfig then return end
	net.id   = id
	net.icon = skillConfig.icon
	net.name = skillConfig.name
	net.type = skillConfig.type
	net.desc = skillConfig.desc
	net.need = skillConfig.need or 0
	net.lv   = skillConfig.skillLv or 0
    -- todo

    net.cd[0] = #skillConfig.cd 
    if net.cd[0] ~= 0 then
 		net.cd[1] = skillConfig.cd[1]
    	net.cd[2] = skillConfig.cd[2]
    end

    local len = #skillConfig.buffers
    for i = 1,len do
        local buffId = skillConfig.buffers[i][1]
        local buffConfig = BufferExcel.buffer[buffId]
        net.buff[i].id = buffId
        net.buff[i].name = buffConfig.name
        net.buff[i].desc = buffConfig.desc
    end
    net.buff[0] = len
    net.lvUpDesc = skillConfig.lvUpDesc
    -- todo
end

-- 封装UpStarCond协议结构体
function makeUpStarCond(net, cond)
	local ttype = cond[1]
	net.type = ttype
	if ttype == HechengLogic.COND_TYPE_HEROID then
		local heroID = cond[2]
		local heroConfig = HeroExcel.hero[heroID]
        local star = cond[4] or heroConfig.star
		net.id = heroID
		net.icon = heroConfig.head 
		net.star = star 
		net.camp = heroConfig.camp 
		net.name = heroConfig.name
        net.grade = heroConfig.grade 
		net.cnt = cond[3]
	elseif ttype == HechengLogic.COND_TYPE_CAMPSTAR then
		net.id = 0
		net.icon = 0
		net.name = ""
        net.grade = 0 
		net.camp = cond[2]
		net.star = cond[3]
		net.cnt = cond[4]
	end
end

-------------------------------- 英雄属性计算 ------------------------------------------
--等级加成
local function lvAdd(lv, upAttrs, attrs)
	for _, upAttr in ipairs(upAttrs) do
		local key = upAttr[1]
		local value = upAttr[2]
		attrs[key] = attrs[key] + value * (lv - 1)
	end
end

--星級加成
local function starAdd(star, atkStarRate, hpStarRate, attrs)
	attrs[RoleDefine.ATK] = attrs[RoleDefine.ATK] * (1 + atkStarRate/10000)
	attrs[RoleDefine.HP] = attrs[RoleDefine.HP] * (1 + hpStarRate/10000)
end

--阶数加成
local function qualityAdd(heroConfig, quality, attrs)
    local qualityConfig = HeroExcel.quality[heroConfig.quality]
    local qualityEnd = quality + 1
	for i = 1, qualityEnd do
		for key, rateConfig in pairs(qualityConfig) do
            local rate = rateConfig[i]
            if rate then
               if key == RoleDefine.DEF or key == RoleDefine.SPEED then
                   attrs[key] = attrs[key] + rate[1]
               else
                   attrs[key] = attrs[key] * rate[1]
               end
            end
		end
	end
end

-- 伙伴基础
function doCalcHero(grid, attrs)
	if not grid and attrs then return end
	local heroConfig = HeroExcel.hero[grid.id]
    local attrConfig = HeroDefine.getAttrConfig(grid.id, grid.star)
    if not attrConfig then
       assert(nil, "attrConfig is nil id "..grid.id.." star "..grid.star)
    end

	for _,v in ipairs(attrConfig.attrs) do
		RoleAttr.updateValue(v[1], v[2], attrs)
	end	

	lvAdd(grid.lv, attrConfig.up, attrs)
	starAdd(grid.star, attrConfig.atkStarRate, attrConfig.hpStarRate, attrs)
	qualityAdd(heroConfig, grid.quality, attrs)
end

-- 时装
function doCalcHeroSkin(skinID, attrs)
	local skinConfig = SkinExcel.skin[skinID]
	for _, v in ipairs(skinConfig.attrs) do
		RoleAttr.updateValue(v[1], v[2], attrs)
	end	
end

-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------

local function sortZhanli(a, b)
	return a[2] > b[2]
end

-- 下发英雄背包列表
function sendHeroBagList(human)
	local msgRet = Msg.gc.GC_HERO_BAG_LIST	
	local cnt = 0
	human.maxZDL = {}
	human.maxZDL.maxHero = {}
	human.maxZDL.heroCnt = 0
	human.maxZDL.zhandouli = 0

	local list = {}
	for index = 1, human.db.heroBag[0] do
        local heroGrid = human.db.heroBag[index]
        if heroGrid then
		    cnt = cnt + 1		
		    HeroGrid.makeHeroSimple(msgRet.list[cnt], heroGrid, index, human)
		    if cnt >= HeroDefine.PAGE_HERO_COUNT then
		    	msgRet.list[0] = cnt
		    	Msg.send(msgRet, human.fd)
		    	cnt = 0
		    end

			list[#list + 1] = {heroGrid.uuid or "", heroGrid.zhandouli or 0}
        end
	end	
	if cnt > 0 then
		msgRet.list[0] = cnt
		Msg.send(msgRet, human.fd)
	end

	if #list > 0 then
		table.sort( list , sortZhanli )
		local maxCnt = human.db.lv >= 100 and 6 or 5
		for i = 1 , maxCnt do
			local heroDb = list[i]
			if heroDb then
				human.maxZDL.heroCnt = human.maxZDL.heroCnt + 1
				human.maxZDL.maxHero[heroDb[1]] = heroDb[2]
				human.maxZDL.zhandouli = human.maxZDL.zhandouli + heroDb[2]
			end
		end
	end

	print(" human onLogin  maxZDL is : ",  human.maxZDL.zhandouli)
end

-- 修正 玩家最高战力
function checkChangeMaxZDL(human, heroGrid)
	if human.maxZDL and heroGrid.uuid then
		if human.maxZDL.maxHero[heroGrid.uuid] then
			human.maxZDL.maxHero[heroGrid.uuid] = heroGrid.zhandouli
			human.maxZDL.zhandouli = 0
			for _, v in pairs(human.maxZDL.maxHero) do
				human.maxZDL.zhandouli = human.maxZDL.zhandouli + v
			end
		else
			local maxCnt = human.db.lv >= 100 and 6 or 5
			if human.maxZDL.heroCnt < maxCnt then
				human.maxZDL.maxHero[heroGrid.uuid] = heroGrid.zhandouli
				human.maxZDL.zhandouli = human.maxZDL.zhandouli + heroGrid.zhandouli
				human.maxZDL.heroCnt = human.maxZDL.heroCnt + 1
			else
				local minZDL = 0
				local minUuid 
				for thisUuid, v in pairs(human.maxZDL.maxHero) do
					minUuid = minZDL == 0 and thisUuid or minUuid
					minZDL = minZDL == 0 and v or minZDL
					if minZDL > v then
						minZDL = v
						minUuid = thisUuid
					end
				end

				if minZDL < heroGrid.zhandouli then
					human.maxZDL.maxHero[minUuid] = nil
					human.maxZDL.maxHero[heroGrid.uuid] = heroGrid.zhandouli
					human.maxZDL.zhandouli = human.maxZDL.zhandouli - minZDL + heroGrid.zhandouli
				end
			end
		end

        print(" checkChangeMaxZDL   ", human.maxZDL.zhandouli)
	end

	
end

-- 发送英雄详细信息：静态,只是1个英雄的
function sendHeroBagStatic(human, id, tuJian)
	local heroConfig = HeroExcel.hero[id]
	if not heroConfig then return end
	
	local msgRet = Msg.gc.GC_HERO_BAG_STATIC
	HeroGrid.makeHeroStatic(msgRet.heroStatic, id, tuJian)
	Msg.send(msgRet, human.fd)
end

-- 玩家身上动态数据
function sendHeroGridDynamic(human, heroGrid, index, isQuery)
	if not isQuery then sendHeroBagUpdate(human, index) end	
	local msgRet = Msg.gc.GC_HERO_BAG_DYNAMIC
	msgRet.index = index or 0
    msgRet.canLv = isHeroLvDot(human, heroGrid) == true and 1 or 0
    msgRet.canUp = isHeroUpDot(human, heroGrid) == true and 1 or 0
    msgRet.canEquip = HeroEquip.isEquipDot(human, heroGrid) == true and 1 or 0
    msgRet.canFuwen = FuwenLogic.isFuwenDot(human, heroGrid) == true and 1 or 0
    msgRet.canJueXing = isHeroJuexingDot(human, index, heroGrid) == true and 1 or 0
	local bingShuState = BingshuLogic.isBingShuDot(human, heroGrid)
	if bingShuState == -1 then
		msgRet.canBingShu = -1 
	else
		msgRet.canBingShu = bingShuState == true and 1 or 0
	end

	HeroGrid.makeHeroDynamic(msgRet.heroDynamic, heroGrid, index, human)
	Msg.send(msgRet, human.fd)
end

-- 配置数据
function sendHeroBagDynamicByID(human, heroID, star)
	local msgRet = Msg.gc.GC_HERO_BAG_DYNAMIC_BY_ID
	HeroGrid.makeHeroDynamicByID(msgRet.heroDynamic, heroID, star)
	Msg.send(msgRet, human.fd)
end

-- 发送英雄详细信息 
function sendHeroBagDynamic(human, id, index, isQuery)
	local heroGrid = getHeroGrid(human, id, index)
	if not heroGrid then return end

	sendHeroGridDynamic(human, heroGrid, index, isQuery)
end

-- 发送英雄添加/变化
function sendHeroBagUpdate(human, index)
	local heroGrid = human.db.heroBag[index]
	if type(heroGrid) ~= "table" then return end

	local msgRet = Msg.gc.GC_HERO_BAG_ADD				
	HeroGrid.makeHeroSimple(msgRet.data, heroGrid, index, human)
	Msg.send(msgRet, human.fd)

end

-- 发送英雄删除
function sendHeroBagDel(human, index)
	local msgRet = Msg.gc.GC_HERO_BAG_DELETE
	msgRet.index = index
	Msg.send(msgRet, human.fd)
end

-- 背包容量查询
function sendHeroBagCap(human)
	calcHeroBagCap(human)
	local nowBuyCnt = human.db.buyCapCnt or 0	
	local msgRet = Msg.gc.GC_HERO_CAP_QUERY
	msgRet.cap = human.db.heroBag[0]
	msgRet.buyZuanshi = (nowBuyCnt + 1) * 100	
	if nowBuyCnt >= HeroDefine.BUY_CAP_CNT then
		msgRet.buyZuanshi = -1  --达到上限
	end
	Msg.send(msgRet, human.fd)
end
-----------------------------------------------------------------------------------------

-- 锁定英雄
function lockHero(human, isLock, heroID, heroIndex)
	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end	
	if isLock == 1 then 
		heroGrid.isLock = true
	elseif isLock == 0 then 
		heroGrid.isLock = nil
	end
	
	local msgRet = Msg.gc.GC_HERO_BAG_LOCK
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	msgRet.type = heroGrid.isLock and 1 or 0
	Msg.send(msgRet, human.fd)
end

-- 返回英雄背包空余格子数
function getEmptyCnt(human)
	local emptyCnt = 0
	for i = 1, human.db.heroBag[0] do
		if human.db.heroBag[i] == nil then
			emptyCnt = emptyCnt + 1	
		end
	end
	return emptyCnt
end

-- 获得英雄背包第一个空格子下标
function getEmptyIndex(human)
	for index = 1, human.db.heroBag[0]do
		local grid = human.db.heroBag[index]
		if grid == nil then			
			return index
		end
	end
end

-- 新增英雄
function addHero(human, id, star, cnt, logType, noSend)
	if cnt < 1 then return end
	local heroConfig = HeroExcel.hero[id]
	if not heroConfig then return end	

	-- 某些英雄自动分解
	local isFenjie, fenjieList = FenjieLogic.autoFenjie(human, id, cnt, logType)
	if isFenjie then
		return nil, fenjieList
	end
	
	-- 先判断英雄背包是否满
	if getEmptyCnt(human) < cnt then
		return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
	end

	local heroIndex, uuid = nil
	for i = 1, cnt do		
		local heroGrid = HeroGrid.createHeroGrid(id,star)
		heroIndex = addHeroByGrid(human, heroGrid, logType, noSend)
        uuid = heroGrid.uuid
	end
	return heroIndex, uuid
end

-- 英雄添加日志
function writeLogHeroAdd(human, logType, heroGrid)
	Log.write(Log.LOGID_OSS_HERO, human.db._id, human.db.account, human.db.name, human.db.lv, 
		LogDefine.DEFINE[logType] + LogDefine.TYPE["hero"] , heroGrid.id, 1, heroGrid.uuid, heroGrid.star)
end

-- 英雄删除日志
function writeLogHeroDel(human, logType, heroGrid)
	Log.write(Log.LOGID_OSS_HERO, human.db._id, human.db.account, human.db.name, human.db.lv, 
		LogDefine.DEFINE[logType] + LogDefine.TYPE["hero"] , heroGrid.id, -1, heroGrid.uuid, heroGrid.star)
end

-- 新增英雄
function addHeroByGrid(human, heroGrid, logType, noSend)
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["hero"] then
		assert()
	end
	
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

	-- 某些英雄自动分解
	local isFenjie, fenjieList = FenjieLogic.autoFenjie(human, heroGrid.id, 1, logType)
	if isFenjie then
		return nil, fenjieList
	end
	
	-- 先判断英雄背包是否满
	if getEmptyCnt(human) < 1 then
		return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
    end

	local emptyIndex = getEmptyIndex(human)
	if not emptyIndex then return end 

    heroGrid.bagIndex = emptyIndex
	human.db.heroBag[emptyIndex] = heroGrid
	ObjHuman.doCalcHero(human, emptyIndex)
	if not noSend then
		sendHeroBagUpdate(human, emptyIndex)
	end	

	onGetNewHero(human, heroGrid, logType, emptyIndex)	

	writeLogHeroAdd(human, logType, heroGrid)
	checkChangeMaxZDL(human, heroGrid)
	return emptyIndex
end

local yunYingActParam = {}
function onGetNewHero(human, heroGrid, logType, heroIndex)
	local heroConfig = HeroExcel.hero[heroGrid.id]
    local grade = heroConfig.grade
	HeroBook.onAddHero(human, heroGrid.id, heroGrid.star)
	RoleHeadLogic.onAddHero(human, heroGrid.id)	
	-- 先知置换 和十星置换 不予计算活动
	if logType ~= "xianzhi_zhihuan" and logType ~= "tenStar_displace" then
		GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_HERO)
		TuiSongLiBao.tuiSongLiBaoOnTask(human, TuiSongLiBao.TUISONGLIBAOTASK_STARS_HERO, heroConfig.star, nil)
		HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE12, heroGrid.star)

        if grade == 4 then
            MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_15,1)
        end
	end	
	XingYaoGongMing.onAddHero(human,heroGrid,heroIndex)

    HeroLogLogic.finishTaskCB(human, HeroLogLogic.HERO_LOG_TYPE_7, 1, heroGrid.id)

    for i in ipairs(yunYingActParam) do
        yunYingActParam[i] = nil
    end
    yunYingActParam[1] = logType
    yunYingActParam[2] = heroGrid.id
    yunYingActParam[3] = 1
    YunYingLogic.onCallBack(human, "onGetNewHeroAct", yunYingActParam)
    
    for i in ipairs(yunYingActParam) do
        yunYingActParam[i] = nil
    end
    yunYingActParam[1] = heroGrid.id
    yunYingActParam[2] = heroGrid.star
    yunYingActParam[3] = 1
    YunYingLogic.onCallBack(human, "onHeroStarChange", yunYingActParam)   
end

-- 根据下标删除英雄
function delHeroByIndex(human, index, logType, noSend)
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["hero"] then
		assert()
	end

	if human.db.heroBag[index] == nil then
		return
	end
	
	SkinLogic.onDelHero(human, index)
	local heroGrid = human.db.heroBag[index]	
    human.db.heroBag[index] = nil
	human.heroAttrs[index] = nil
	
	if not noSend then
		sendHeroBagDel(human, index)
	end
	
	-- 删除酒馆任务中的上战的英雄
	BarTaskLogic.heroIndexByDelForPos(human, index)	
	-- 删除 默认出站队列中的 英雄	
	CombatPosLogic.heroIndexByDelForPos(human, heroGrid.uuid)
	XingYaoGongMing.onDelHero(human,heroGrid,index)
	ObjHuman.doCalc(human)

	writeLogHeroDel(human, logType, heroGrid)	
end




-- 英雄升级
function heroLvUp(human, heroID, heroIndex)
	local heroGrid = human.db.heroBag[heroIndex]	
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end		
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_LV) then
		return
	end
	
	-- 判断等级上限
	local star = heroGrid.star
	local nowLv = heroGrid.lv
	local maxLv = HeroGrid.getMaxLv(star, heroGrid.quality)
	local upLv, needJinbi, needSoulCnt = HeroGrid.getLevelUpCnt(human, nowLv, maxLv)
	--print(" upLv, needJinbi, needSoulCnt", upLv, needJinbi, needSoulCnt)
	if upLv < 1 then return end
	
	-- 判断消耗材料
	if human.db.jinbi < needJinbi then
		return Broadcast.sendErr(human, Lang.COMMON_NO_JINBI)
	end
	if BagLogic.getItemCnt(human, ItemDefine.ITEM_GREEN_EXP_ID) < needSoulCnt then
		local strName = ItemDefine.getValue(ItemDefine.ITEM_GREEN_EXP_ID, "name")
		return Broadcast.sendErr(human, Util.format(Lang.COMMON_NO_ITEM, strName))
	end
	
	-- 扣道具
	ObjHuman.updateJinbi(human, -needJinbi, "hero_up")
	BagLogic.delItem(human, ItemDefine.ITEM_GREEN_EXP_ID, needSoulCnt, "hero_up")
	
	-- 改db
	heroGrid.lv = nowLv + upLv

	ObjHuman.doCalcHero(human, heroIndex)
	sendHeroBagDynamic(human, heroID, heroIndex)
	
	local msgRet = Msg.gc.GC_HERO_LEVEL_UP
	msgRet.id = heroID
	msgRet.index = heroIndex
	Msg.send(msgRet, human.fd)

	GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_HEROUP)
	refreshDot(human, heroGrid.uuid)

    if nowLv < 50 and heroGrid.lv >= 50 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_6,1)
    elseif nowLv < 100 and heroGrid.lv >= 100 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_14,1)
    elseif nowLv < 200 and heroGrid.lv >= 200 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_20,1)
    elseif nowLv < 145 and heroGrid.lv >= 145 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_17,1)
    elseif nowLv < 185 and heroGrid.lv >= 185 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_18,1)
    end
	
	XingYaoGongMing.onHeroLvUp(human,heroGrid,heroIndex)
    Log.write(Log.LOGID_OSS_HEROLVUP, human.db._id, human.db.account, human.db.name, heroGrid.uuid, nowLv, heroGrid.lv)
	checkChangeMaxZDL(human, heroGrid)
end

-- 英雄升阶查询
function heroUpgradeQuery(human, heroID, heroIndex)
	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end

	local cf = HeroExcel.hero[heroID]
	if not cf then return end

	local star = cf.star
	local nextQuality = heroGrid.quality + 1		
	local maxLv = HeroGrid.getMaxLv(heroGrid.star, nextQuality)
	local upcf = UpNeedExcel.upQuality[nextQuality]
	if not maxLv or not upcf then 
		return Broadcast.sendErr(human, Lang.HERO_UPGRADE_ERR_FULL)
	end

	local nextHeroGrid = HeroGrid.getHeroGridCalcCache(heroGrid)
	nextHeroGrid.quality = nextQuality
	local nextAttrs = RoleAttr.calcHeroGrid(nextHeroGrid, heroIndex, human)
	local zhandouli = RoleAttr.calcZhandouli(nextAttrs)	

	local msgRet = Msg.gc.GC_HERO_UPGRADE_QUERY
	msgRet.id = heroID
	msgRet.index = heroIndex
	local net = msgRet.data
	net.id = heroID
	net.maxLv = maxLv	
	net.zhandouli = zhandouli
	net.attr[0] = 4
	net.attr[1].key = RoleDefine.ATK
	net.attr[1].value = nextAttrs[RoleDefine.ATK]
	net.attr[2].key = RoleDefine.HP
	net.attr[2].value = nextAttrs[RoleDefine.HP] 
	net.attr[3].key = RoleDefine.SPEED
	net.attr[3].value = nextAttrs[RoleDefine.SPEED] 	
	net.attr[4].key = RoleDefine.DEF
	net.attr[4].value = nextAttrs[RoleDefine.DEF] 	
	net.needJinbi = upcf.money
	net.needItemCnt = upcf.jinjieshi
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd) 
end

-- 英雄升阶
function heroUpgradeDo(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end

    if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_LV) then
	   return
	end
	
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end
	local star = heroGrid.star
	local maxQuality = HeroGrid.getMaxQuality(star)
	local nextQuality = heroGrid.quality + 1
				
	-- 判断阶数上限
	if heroGrid.quality >= maxQuality then
		return
	end
	local upcf = UpNeedExcel.upQuality[nextQuality]
	if not upcf then return end
	
	-- 判断消耗材料
	local needJinbi = upcf.money
	local needItemCnt = upcf.jinjieshi
	if human.db.jinbi < needJinbi then
		return Broadcast.sendErr(human, Lang.COMMON_NO_JINBI)
	end
	local nowItemCnt = BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID)
	if nowItemCnt < needItemCnt then
		local strName = ItemDefine.getValue(ItemDefine.ITEM_HERO_UPGRADE_ID, "name")
		return Broadcast.sendErr(human, Util.format(Lang.COMMON_NO_ITEM, strName))
	end
	
	-- 扣材料
	ObjHuman.updateJinbi(human, -needJinbi, "hero_upgrade")
	BagLogic.delItem(human, ItemDefine.ITEM_HERO_UPGRADE_ID, needItemCnt, "hero_upgrade")
	
	-- 改db
	heroGrid.quality = nextQuality	
	ObjHuman.doCalcHero(human, heroIndex)
	sendHeroBagDynamic(human, heroID, heroIndex)
	
    GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_UPGRADE)
    ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_25,1)
	local msgRet = Msg.gc.GC_HERO_UPGRADE_DO
	msgRet.id = heroID
	msgRet.index = heroIndex
	Msg.send(msgRet, human.fd)
	refreshDot(human, heroGrid.uuid)
	
	XingYaoGongMing.onHeroUpgrade(human,heroGrid,heroIndex)
	checkChangeMaxZDL(human, heroGrid)
end

-- 重算背包熔炼
function calcHeroBagCap(human)
	local buyCnt = math.min(human.db.buyCapCnt or 0, HeroDefine.BUY_CAP_CNT)
	local heroBagCnt = HeroDefine.HERO_BAG_CNT 

	heroBagCnt = heroBagCnt + (VipLogic.getPowerArgs(human, VipLogic.VIP_POWER12) or 0)
	heroBagCnt = heroBagCnt + HeroDefine.HERO_BAG_BUY_ADD_CNT * buyCnt -- 购买获得背包格子

    if human.db.blue ~= nil and human.db.blue.isAdd ~= nil then -- 特权
        local cnt = TequanExcel.tequan[2].privilege
        heroBagCnt = heroBagCnt + cnt
    end

    if human.db.yellow ~= nil and human.db.yellow.isAdd ~= nil then -- 特权
        local cnt = TequanExcel.tequan[1].privilege
        heroBagCnt = heroBagCnt + cnt
    end

    -- 封印之章特权
    local cjPrivilege = ChengjiuLogic.checkPrivilege(human,ChengjiuDefine.PRIVILEGE_TYPE_1)
    if cjPrivilege then
        heroBagCnt = heroBagCnt + cjPrivilege
    end

    -- 特殊服务器处理
    -- vip需求砍掉之后，导致有的玩家英雄数量超过背包数量
    -- 经策划确认，140001-140021 服务器所有玩家增加背包数量300
    if Config.SVR_INDEX >= 140001 and Config.SVR_INDEX <= 140021 then
        heroBagCnt = heroBagCnt + 300
    end

    human.db.heroBag[0] = heroBagCnt
end

-- 购买英雄背包容量
function buyHeroCap(human)
	-- 上限判断
	local nowBuyCnt = human.db.buyCapCnt or 0
	if nowBuyCnt >= HeroDefine.BUY_CAP_CNT then 
		return Broadcast.sendErr(human, Lang.HERO_BAG_BUY_CAP_NO_CNT)
	end

	-- 判断消耗
	local needZuanshi = (nowBuyCnt + 1) * 100	
	if not ObjHuman.checkRMB(human, needZuanshi) then
		return
	end
	
	-- 扣消耗
	ObjHuman.decZuanshi(human, -needZuanshi, "buy_hero_cap")
	
	-- 改db	
	human.db.buyCapCnt = nowBuyCnt + 1
	sendHeroBagCap(human)
	Broadcast.sendErr(human, Lang.ITEM_BUY_SUCCESS)
end

-- 最大觉醒
function sendHeroJueXingMax(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local msgRet = Msg.gc.GC_HERO_JUEXING_QUERY_MAX
	msgRet.id = heroID
	msgRet.index = heroIndex
	Msg.send(msgRet, human.fd)
end

local JUEXING_SKILL_DIFF_LIST = {}
function getSkillDiffList(cf1, cf2)
	local diffCnt = 0
	for i = 1, #cf2.skillList do
		local skillID1 = cf1.skillList[i]
		local skillID2 = cf2.skillList[i]
		if skillID1 ~= skillID2 then
			diffCnt = diffCnt + 1
			local tb = JUEXING_SKILL_DIFF_LIST[diffCnt] or {}
			JUEXING_SKILL_DIFF_LIST[diffCnt] = tb
			tb[1] = skillID1
			tb[2] = skillID2			
		end
	end
	for i = 1, #cf2.beSkillList do
		local skillID1 = cf1.beSkillList[i]
		local skillID2 = cf2.beSkillList[i]
		if skillID1 ~= skillID2 then
			diffCnt = diffCnt + 1
			local tb = JUEXING_SKILL_DIFF_LIST[diffCnt] or {}
			JUEXING_SKILL_DIFF_LIST[diffCnt] = tb
			tb[1] = skillID1
			tb[2] = skillID2
		end
	end
	return diffCnt, JUEXING_SKILL_DIFF_LIST
end

-- 英雄觉醒预览
local JUEXING_SPEED_UP = {[4]=10}
local JUEXING_ATK_UP = {[5]=40,[6]=40,[7]=40,[8]=40,[9]=40,[10]=20,[11]=20,[12]=20}
local JUEXING_HP_UP = {[5]=50,[6]=50,[7]=50,[8]=50,[9]=50,[10]=30,[11]=30,[12]=30}
function heroJueXingQuery(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

    -- 判断是否达到开放等级
	local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then
		if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
		elseif upStarNeedLv then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
		end
		return
	end
    
    local attrConfig = HeroDefine.getAttrConfig(heroID, heroGrid.star)
    if not attrConfig then return end

	local nextAttrConfig = HeroDefine.getNextAttrConfig(heroID, heroGrid.star)
	if not nextAttrConfig then 
       return sendHeroJueXingMax(human, heroID, heroIndex)
    end
	

	local msgRet = Msg.gc.GC_HERO_JUEXING_QUERY
	local dataNet = msgRet.data
	local maxQuality = HeroGrid.getMaxQuality(attrConfig.star)
	local nextMaxQuality = HeroGrid.getMaxQuality(nextAttrConfig.star)
	-- 判断是否达到开放等级
	local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then
		if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
		elseif upStarNeedLv then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
		end
		return
	end
	dataNet.id = heroID
	dataNet.index = heroIndex
	dataNet.star = heroGrid.star
	dataNet.nextStar = nextAttrConfig.star
	dataNet.maxLv = HeroGrid.getMaxLv(heroGrid.star, maxQuality)	
	dataNet.nextMaxLv = HeroGrid.getMaxLv(nextAttrConfig.star, nextMaxQuality)

	-- 展示变化的技能
	local diffCnt, diffList = getSkillDiffList(attrConfig, nextAttrConfig)
    diffCnt = diffCnt > #dataNet.skillUp and #dataNet.skillUp or diffCnt
	dataNet.isAllSkillUp = (diffCnt > 1) and 1 or 0
    dataNet.skillUp[0] = diffCnt
    for i=1, diffCnt do
	   makeSkillNet(dataNet.skillUp[i], diffList[i][2])
    end
	dataNet.speedUp = JUEXING_SPEED_UP[heroConfig.star] or 0
	dataNet.atkUpRate = JUEXING_ATK_UP[heroConfig.star] or 0
	dataNet.hpUpRate = JUEXING_HP_UP[heroConfig.star] or 0

	dataNet.needItems[0] = #attrConfig.needItems
	for i = 1, dataNet.needItems[0] do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		Grid.makeItem(dataNet.needItems[i], itemID, itemCnt)
	end
	dataNet.needHeros[0] = 0
	for i = 1, #attrConfig.cond do
		dataNet.needHeros[0] = dataNet.needHeros[0] + 1
		local condNet = dataNet.needHeros[dataNet.needHeros[0]]
		makeUpStarCond(condNet, attrConfig.cond[i])
	end	
	dataNet.needItemCnt = attrConfig.jinjieshi
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

function fontJueXingHeroNet(net, heroGrid, index, human)
	local attrs = ObjHuman.getHeroAttrs(human, index)  
	HeroGrid.makeHeroDynamic(net.dynamicData, heroGrid, index, human)
	HeroGrid.makeHeroSimple(net.simpleData, heroGrid, index, human)
	net.zhandouli = attrs[RoleDefine.ZHANDOULI] or 0
	net.atk = attrs[RoleDefine.ATK] or 0
	net.hp = attrs[RoleDefine.HP] or 0
	net.def = attrs[RoleDefine.DEF] or 0
	net.speed = attrs[RoleDefine.SPEED] or 0
end

-- 检查世界等级或者玩家等级是否满足条件
-- 检查达到角色等级或者世界等级
function isFixUpStarLv(human, targetStar)
	local config = HeroExcel.star[targetStar]
	if not config then 
		return false
	end
	if config.upStarNeedLv >= 0 and human.db.lv >= config.upStarNeedLv then
		return true, config.upStarNeedLv, config.upStarNeedWorldLv
	end 
	if config.upStarNeedWorldLv >= 0 and GlobalWorld.getWorldLv() >= config.upStarNeedWorldLv then
		return true, config.upStarNeedLv, config.upStarNeedWorldLv
	end 
	return false, config.upStarNeedLv, config.upStarNeedWorldLv	
end

-- 英雄觉醒
local yunYingActParam = {}
function heroJueXingDo(human, heroID, heroIndex, inputIDList, inputIndexList)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

    local attrConfig = HeroDefine.getAttrConfig(heroID, heroGrid.star)
    if not attrConfig then return end

	local nextAttrConfig = HeroDefine.getNextAttrConfig(heroID, heroGrid.star)
	if not nextAttrConfig then return end

	-- 判断是否达到开放等级
	local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then
		if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
		elseif upStarNeedLv then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
		end
		return
	end

	-- 判断消耗材料
	local needItemCnt = attrConfig.jinjieshi
	if not BagLogic.checkItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID, needItemCnt) then
		return 
	end

	-- 额外材料
	for i = 1, #attrConfig.needItems do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		if not BagLogic.checkItemCnt(human, itemID, itemCnt) then
			return
		end
	end
	
	-- 英雄材料
	if not HechengLogic.checkCond(human, inputIDList, inputIndexList, attrConfig.cond) then
		return Broadcast.sendErr(human, Lang.HERO_JUEXING_CAILIAO_ERR)
	end
	-- 比较特别的情况。。
	for i = 1, inputIndexList[0] do
		if inputIndexList[i] == heroIndex then
			return -- 本体同时作为材料，骗分解材料
		end
	end

	-- 扣消耗
	BagLogic.delItem(human, ItemDefine.ITEM_HERO_UPGRADE_ID, needItemCnt, "hero_juexing")
	local fenjieList = FenjieLogic.fenjie(human, FenjieLogic.FENJIE_DO_JUEXING, inputIDList, inputIndexList)	
	-- 额外材料
	for i = 1, #attrConfig.needItems do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		BagLogic.delItem(human, itemID, itemCnt, "hero_juexing")
	end

	local msgRet = Msg.gc.GC_HERO_JUEXING_DO
	msgRet.id = heroID 
	msgRet.index = heroIndex
    msgRet.upStarNeedLv = upStarNeedLv
    msgRet.upStarNeedWorldLv = upStarNeedWorldLv
	fontJueXingHeroNet(msgRet.oldData, heroGrid, heroIndex, human)

    -- 继承英雄等级 阶数 装备 水晶 
    writeLogHeroDel(human, "hero_juexing", heroGrid)
	heroGrid.star = nextAttrConfig.star
	onGetNewHero(human, heroGrid, "hero_juexing", heroIndex)	
	ObjHuman.doCalcHero(human, heroIndex)

	sendHeroBagDynamic(human, heroGrid.id, heroIndex)
	writeLogHeroAdd(human, "hero_juexing", heroGrid)

	fontJueXingHeroNet(msgRet.newData, heroGrid, heroIndex, human)
	local diffCnt, diffList = getSkillDiffList(attrConfig, nextAttrConfig)
    diffCnt = diffCnt > #msgRet.skillUp and #msgRet.skillUp or diffCnt
	msgRet.isAllSkillUp = (diffCnt > 1) and 1 or 0
    msgRet.skillUp[0] = diffCnt
    for i=1, diffCnt do
	   makeSkillNet(msgRet.skillUp[i], diffList[i][2])
    end
	
	msgRet.itemList[0] = 0
	if fenjieList then
		for itemID, itemCnt in pairs(fenjieList) do
			if msgRet.itemList[0] >= #msgRet.itemList then
				break
			end
			msgRet.itemList[0] = msgRet.itemList[0] + 1
			Grid.makeItem(msgRet.itemList[msgRet.itemList[0]], itemID, itemCnt)
		end
	end
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)

    ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE12, nextAttrConfig.star,heroGrid.id)

	local newstar = nextAttrConfig.star or 0
	local newcamp =	heroConfig.camp or 0
	LiLianLogic.onCallback(human,LiLianLogic.LILIAN_OUTID24,1,newcamp,newstar)
    if newstar == 5 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_11,1)
    end

    if newstar >= 5 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_13,1)
    end

    if newstar == 6 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_16,1)
        JibanLogic.onCallback(human,2,newstar)
	end

    if newstar == 10 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_23,1)
	end

	checkChangeMaxZDL(human, heroGrid)

    HeroLogLogic.finishTaskCB(human, HeroLogLogic.HERO_LOG_TYPE_8, 1, heroID, newstar)

    for i in ipairs(yunYingActParam) do
        yunYingActParam[i] = nil
    end
    yunYingActParam[1] = heroID
    yunYingActParam[2] = newstar
    yunYingActParam[3] = 1
    YunYingLogic.onCallBack(human, "onHeroStarChange", yunYingActParam)
end


-- 英雄重生预览 
function heroChongShengQuery(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	if heroGrid.isLock then
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_LOCK)
	end

	local chongShengConfig = UpNeedExcel.chongSheng[heroGrid.star]
	if not chongShengConfig then -- 只能重生7-9星
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

    -- 没有对应5星的存在
    local attrConfig = HeroDefine.getAttrConfig(heroID, CHONGSHENG_RETURN_STAR)
	if not attrConfig then 
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

	local suipianID = SuipianLogic.getSuipianIDbyHeroID(heroID)
	if not suipianID then -- 没有对应的本体碎片
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_SUIPIANID)
	end

	local otherSuipianID = chongShengConfig.suipianIDs[heroConfig.camp]
	if not otherSuipianID then -- 阵容不对
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

	local msgRet = Msg.gc.GC_HERO_CHONGSHENG_QUERY
	msgRet.id = heroID
	msgRet.index = heroIndex
	msgRet.needItemCnt = chongShengConfig.needItemCnt
	Grid.makeItem(msgRet.bentiSuipian, suipianID, chongShengConfig.bentiCnt)
	Grid.makeItem(msgRet.otherSuipian, otherSuipianID, chongShengConfig.suipianCnt)
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 英雄重生
function heroChongShengDo(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	if heroGrid.isLock then
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_LOCK)
	end

	local chongShengConfig = UpNeedExcel.chongSheng[heroGrid.star]
	if not chongShengConfig then -- 只能重生7-9星
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

    local attrConfig = HeroDefine.getAttrConfig(heroID, CHONGSHENG_RETURN_STAR)
	if not attrConfig then 
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

	local suipianID = SuipianLogic.getSuipianIDbyHeroID(heroID)
	if not suipianID then -- 没有对应的本体碎片
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_SUIPIANID)
	end

	local otherSuipianID = chongShengConfig.suipianIDs[heroConfig.camp]
	if not otherSuipianID then -- 阵营不对
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

    local nowItemCnt = BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_CHONGSHENG_ID)
	local needItemCnt = chongShengConfig.needItemCnt

    if nowItemCnt < needItemCnt then
        local strName = ItemDefine.getValue(ItemDefine.ITEM_HERO_CHONGSHENG_ID, "name")
		local strRet = Util.format(Lang.COMMON_NO_ITEM, strName)
		return Broadcast.sendErr(human, strRet)
    end

    -- 删除材料
    BagLogic.delItem(human, ItemDefine.ITEM_HERO_CHONGSHENG_ID, needItemCnt, "hero_chongsheng")

	-- 重置到初始返还的材料
	local upList = getResetReturnItems(heroGrid)


	-- 先删除英雄
	delHeroByIndex(human, heroIndex, "hero_chongsheng")

    -- 返还装备
	for i = 1, ItemDefine.EQUIP_MAX_CNT do
		if i ~= ItemDefine.EQUIP_SUBTYPE_SHUIJIN and 
			heroGrid.equip and heroGrid.equip[i] then
			local equipGrid = heroGrid.equip[i]
            if equipGrid then
			    EquipLogic.addByEquipGrid(human, equipGrid, "hero_chongsheng")
            end
		end
	end

	-- 返还符文
	for i = 1, 2 do
		local fuwenGrid = heroGrid.fuwen and heroGrid.fuwen[i]
		if fuwenGrid and fuwenGrid.id then
			FuwenLogic.addByGrid(human, fuwenGrid, "hero_chongsheng")
		end
	end

	-- 再给东西
	BagLogic.addItem(human, suipianID, chongShengConfig.bentiCnt, "hero_chongsheng")
	BagLogic.addItem(human, otherSuipianID, chongShengConfig.suipianCnt, "hero_chongsheng")
	for itemID, itemCnt in pairs(upList) do
		BagLogic.addItem(human, itemID, itemCnt, "hero_chongsheng")
	end
	
	-- 通知客户端
	local msgRet = Msg.gc.GC_HERO_CHONGSHENG_DO
	msgRet.list[0] = 2
	Grid.makeItem(msgRet.list[1], suipianID, chongShengConfig.bentiCnt)
	Grid.makeItem(msgRet.list[2], otherSuipianID, chongShengConfig.suipianCnt)
	for itemID, itemCnt in pairs(upList) do
		msgRet.list[0] = msgRet.list[0] + 1
		Grid.makeItem(msgRet.list[msgRet.list[0]], itemID, itemCnt)
	end
	msgRet.list[0] = EquipLogic.makeEquipItem(human, msgRet.list, msgRet.list[0])
	Msg.send(msgRet, human.fd)

	checkChangeMaxZDL(human, heroGrid)
end

-- 回退
local HUITUI_HERO_LIST = {}
local HUITUI_ITEM_LIST = {}
function getHuituiReturns(heroGrid)
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end
	local config = UpNeedExcel.huiTui[heroGrid.star]
	if not config then return end
	local targetID = heroGrid.id
	if not targetID then return end	
    -- 13星无法升级，但可以回退
    if heroGrid.star < 13 then
        local upStarConfig = HeroDefine.getNextAttrConfig(heroGrid.id, heroGrid.star)
	    -- 不能升星的话也不能回退
	    if not upStarConfig then
	    	return
	    end
    end
	Util.cleanTable(HUITUI_HERO_LIST)
	Util.cleanTable(HUITUI_ITEM_LIST)
	local maxLv = HeroGrid.getMaxLv(config.targetStar, heroGrid.quality)
	local lv = heroGrid.lv
	if heroGrid.oldLV then
		lv = heroGrid.oldLV
	end
	
	local targetLv = math.min(lv, maxLv)
	-- 升级 不将阶
	for i = targetLv + 1, lv do
		local upcf = UpNeedExcel.upLv[i]
		if upcf then
			HUITUI_ITEM_LIST[ItemDefine.ITEM_GREEN_EXP_ID] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_GREEN_EXP_ID] or 0) + upcf.soul
			HUITUI_ITEM_LIST[ItemDefine.ITEM_JINBI_ID] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

    -- 圣星文书
    HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_BOOK] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_BOOK] or 0) + config.upBook
	-- 进阶石
	HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_ID] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + config.jinjieshi
	-- 5星本体碎片数量 
	local fiveBentiID = heroGrid.id
	local fiveBentiSuipianID = SuipianLogic.getSuipianIDbyHeroID(fiveBentiID)

	HUITUI_ITEM_LIST[fiveBentiSuipianID] = (HUITUI_ITEM_LIST[fiveBentiSuipianID] or 0) + config.fiveBentiCnt
	-- 5星同系碎片数量
	local materialConfig = UpNeedExcel.huiTuiMaterial[heroConfig.camp]
	HUITUI_ITEM_LIST[materialConfig.fiveHeroSuipian] = (HUITUI_ITEM_LIST[materialConfig.fiveHeroSuipian] or 0) + config.fiveSuipianCnt
	-- 9星傀儡数量
    local nineHeroCnt = (HUITUI_HERO_LIST[9] and HUITUI_HERO_LIST[9][2] or 0) + config.nineHeroCnt
	HUITUI_HERO_LIST[9] = {materialConfig.nineHero, nineHeroCnt}
	-- 10星傀儡数量
    local tenHeroCnt = (HUITUI_HERO_LIST[10] and HUITUI_HERO_LIST[10][2] or 0) + config.tenHeroCnt
	HUITUI_HERO_LIST[10] = {materialConfig.tenHero, tenHeroCnt}
	return config.targetStar, targetLv, config, HUITUI_ITEM_LIST, HUITUI_HERO_LIST
end

-- 回退查询
function sendHuituiQuery(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	local star, targetLv, config, items, heros = getHuituiReturns(heroGrid)
	if not star then
		return Broadcast.sendErr(human, Lang.HERO_HUITUI_ERR_STAR)
	end

	local msgRet = Msg.gc.GC_HERO_HUITUI_QUERY
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	HeroGrid.makeHeroSimple(msgRet.oldSimple, heroGrid, heroIndex, human)
	local others = HeroGrid.createOthers(targetLv, nil,nil, star)
	HeroGrid.makeHeroSimpleByID(msgRet.newSimple, heroID, heroIndex, others, nil, true)
	HeroGrid.makeHeroSimpleByGeneral(msgRet.newSimple, heroID)
	Grid.makeItem(msgRet.needItem, ItemDefine.ITEM_HERO_HUITUI_ID, config.needItemCnt)
	msgRet.returnItems[0] = 0
	for itemID, itemCnt in pairs(items) do
		if msgRet.returnItems[0] >= #msgRet.returnItems then
			break
		end
		if itemCnt > 0 then
			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemID, itemCnt)
		end
	end
	msgRet.returnHeros[0] = 0
	for star, v in pairs(heros) do
        local rHeroID = v[1]
        local rHeroCnt = v[2]
		for i = 1, rHeroCnt do
			if msgRet.returnHeros[0] >= #msgRet.returnHeros then
				break
			end
            local others = HeroGrid.createOthers(1, nil,nil, star)
			msgRet.returnHeros[0] = msgRet.returnHeros[0] + 1
			local heroNet = msgRet.returnHeros[msgRet.returnHeros[0]]
			HeroGrid.makeHeroSimpleByID(heroNet, rHeroID, nil, others, human)
			HeroGrid.makeHeroSimpleByGeneral(heroNet, rHeroID)
            heroNet.star = star
		end
	end
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)	
end

-- 回退操作
function huituiHero(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	local star, targetLv, config, items, heros = getHuituiReturns(heroGrid)
	if not star then
		return Broadcast.sendErr(human, Lang.HERO_HUITUI_ERR_STAR)
	end
	if heroGrid.isLock then
		return Broadcast.sendErr(human, Lang.HERO_HUITUI_ERR_LOCK)
	end
	local needHeroBagCnt = 0
	for star, v in pairs(heros) do
        local rHeroCnt = v[2]
		needHeroBagCnt = needHeroBagCnt + rHeroCnt
	end
	-- 检查英雄背包空间
	if getEmptyCnt(human) < needHeroBagCnt then
		return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
	end

	if not BagLogic.checkItemCnt(human, ItemDefine.ITEM_HERO_HUITUI_ID, config.needItemCnt) then
		return
	end

	BagLogic.delItem(human, ItemDefine.ITEM_HERO_HUITUI_ID, config.needItemCnt, "hero_huitui")

	heroGrid.star = star
	heroGrid.lv = targetLv
	XingYaoGongMing.onDelHero(human,heroGrid,heroIndex)
	ObjHuman.doCalcHero(human, heroIndex)
	sendHeroBagDynamic(human, heroID, heroIndex)
	writeLogHeroAdd(human, "hero_huitui", heroGrid)

	for itemID, itemCnt in pairs(items) do
		if itemCnt > 0 then
			BagLogic.addItem(human, itemID, itemCnt, "hero_huitui")
		end
	end
	for star,v in pairs(heros) do
        local rHeroID = v[1]
        local rHeroCnt = v[2]
		if rHeroCnt > 0 then
			addHero(human, rHeroID,star, rHeroCnt, "hero_huitui")
		end
	end
	
	local msgRet = Msg.gc.GC_HERO_HUITUI
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	HeroGrid.makeHeroSimple(msgRet.newSimple, heroGrid, heroIndex, human)
	msgRet.returnItems[0] = 0
	for itemID, itemCnt in pairs(items) do
		if msgRet.returnItems[0] >= #msgRet.returnItems then
			break
		end
		if itemCnt > 0 then
			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemID, itemCnt)
		end
	end
	msgRet.returnHeros[0] = 0
	for star,v in pairs(heros) do
        local rHeroID = v[1]
        local rHeroCnt = v[2]
		for i = 1, rHeroCnt do
			if msgRet.returnHeros[0] >= #msgRet.returnHeros then
				break
			end
			msgRet.returnHeros[0] = msgRet.returnHeros[0] + 1
			local heroNet = msgRet.returnHeros[msgRet.returnHeros[0]]
			HeroGrid.makeHeroSimpleByID(heroNet, rHeroID, nil, nil, human)
            heroNet.star = star
		end
	end
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)	

	checkChangeMaxZDL(human, heroGrid)
end

function getHeroGrid(human, heroID, heroIndex)
    if not heroID then return end
    if not heroIndex then return end
	local heroGrid = human.db.heroBag[heroIndex]
	if type(heroGrid) ~= "table" or heroGrid.id ~= heroID then
		return
	end
	return heroGrid
end

-- 根据uuid 获取heroGrid
function getHeroGridByUuid(human, uuid)
    if not uuid or uuid == "" or uuid == "0" then return end

    for index = 1, human.db.heroBag[0] do
       local heroGrid = human.db.heroBag[index]
       if heroGrid and type(heroGrid) == "table" then
          if heroGrid.uuid == uuid then
             return heroGrid
          end
       end
    end

    return nil
end

-- 获取下标英雄id 
function getHeroIdByIndex(human, heroIndex)
    if heroIndex <= 0 then
       return
    end

	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil then
		return
	end
	return heroGrid.id
end

function makeHeroShare(msg, heroGrid, bagIndex, human)
	if type(heroGrid) ~= "table" then return end
	local heroConfig = HeroExcel.hero[heroGrid.id]
    if not heroConfig then return end

    msg.uuid = human.db._id
    msg.heroIndex = bagIndex
	HeroGrid.makeHeroSimple(msg.heroSimple, heroGrid, bagIndex, human)
	HeroGrid.makeHeroStatic(msg.heroStatic, heroGrid.id)
	HeroGrid.makeHeroDynamic(msg.heroDynamic, heroGrid, bagIndex, human)
	
	-- 装备信息
    msg.equips[0] = 0
	for i = 1, ItemDefine.EQUIP_MAX_CNT do
		local equipGrid = heroGrid.equip and heroGrid.equip[i]
		if equipGrid then
			msg.equips[0] = msg.equips[0] + 1
			local equipNet = msg.equips[msg.equips[0]] 
			Grid.makeItem(equipNet, equipGrid.id, 1, heroGrid.shuijingAttrID, equipGrid)
		end
	end
	-- 符文
    msg.fuWens[0] = 0
    for i = 1, 2 do
    	local fuwenData = heroGrid.fuwen and heroGrid.fuwen[i]
		if fuwenData and fuwenData.id then
			msg.fuWens[0] = msg.fuWens[0] + 1
			local fuwenNet = msg.fuWens[msg.fuWens[0]]
            fuwenNet.pos = i
			Grid.makeItem(fuwenNet.fuwen, fuwenData.id, 1, nil, fuwenData, i,0)
		end
	end
	return true
end

function makeHeroShareMonster(msg, monsterID, mosnterLv)
	local others = HeroGrid.createOthers(mosnterLv)
	msg.uuid = ""
	msg.heroIndex = 0
    HeroGrid.makeHeroSimpleByMonsterID(msg.heroSimple, monsterID, others)		
	HeroGrid.makeHeroStatic(msg.heroStatic, monsterID)
	HeroGrid.makeHeroDynamicByID(msg.heroDynamic, monsterID)	
	msg.equips[0] = 0
	msg.fuWens[0] = 0
end

function getHeroShareGrid(uuid, heroIndex)
    local fakeHuman = ObjHuman.onlineUuid[uuid]
	if not fakeHuman then
		local db = RoleDBLogic.getDb(uuid, RoleLogic.getCombatField())
		if not db then
			return 
		end
		fakeHuman = {db = db}
	end
	local bagIndex = heroIndex

	local heroGrid = bagIndex and fakeHuman.db.heroBag[bagIndex]
	return heroGrid, bagIndex, fakeHuman
end

function shareData(human, uuid, heroIndex)
	local msgRet = Msg.gc.GC_HERO_SHARE_DATA
	local heroGrid, bagIndex, fakeHuman = getHeroShareGrid(uuid, heroIndex) 
	if heroGrid then
		if not makeHeroShare(msgRet.data, heroGrid, bagIndex, fakeHuman) then
			return
		end
	else
		local monsterID, mosnterLv = JjcLogic.getHeroShareMonster(uuid, heroIndex)
		if not monsterID then return end
		makeHeroShareMonster(msgRet.data, monsterID, mosnterLv)
	end
	Msg.send(msgRet, human.fd)
end

-- 获取英雄背包中 最大等级的英雄
function getHeroBagMaxLev(human)
	local maxLv = 1
	for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 and heroGrid.lv > maxLv then
			maxLv = heroGrid.lv
		end
	end
	return maxLv
end

-- 获取英雄背包中 最大星级的英雄
function getHeroBagMaxFuNeng(human)
	local maxStar = 0
	for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 and heroGrid.id then 
			local heroConfig = HeroExcel.hero[heroGrid.id]
			if heroConfig and heroConfig.star > 10 then
				local star = heroConfig.star - 10 
				if star > maxStar then
					maxStar = star
				end
				if maxStar >= HERO_MAX_STAR - 10 then
					return maxStar
				end
			end
		end
		
	end
	return maxStar
end

-- 战力最高的6个英雄战力和
local function sortCombat(a, b)
	return a.zhandouli > b.zhandouli
end

local HeroSortTable = {}
function getHerosZDL(human)
	Util.cleanTable(HeroSortTable)
	local len = 0
	for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 then
            len = len + 1
            HeroSortTable[len] = heroGrid		
		end
	end
	if len > 1 then
		table.sort(HeroSortTable, sortCombat)
	end
	local zhandouli = 0
	for i = 1, 6 do
		local grid = HeroSortTable[i]
        zhandouli = zhandouli + (grid and grid.zhandouli or 0)
	end
    return zhandouli
end

-- 
function getHeroMaxZDL(human, camp)
	local zhandouli = 0
	local maxGrid = nil
	for index,heroGrid in pairs(human.db.heroBag) do
        if index ~= 0 then
		    local heroConfig = heroGrid and HeroExcel.hero[heroGrid.id]
		    if heroConfig and ((camp or 0) == 0 or heroConfig.camp == camp) 
		    	and heroGrid.zhandouli > zhandouli then
		    	zhandouli = heroGrid.zhandouli
		    	maxGrid = heroGrid 
		    end
        end
	end
	return zhandouli, maxGrid
end

-- 武将系统红点
function isDot(human)
    if human.db.lv < 9 then
       return false
    end

	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
	if not combatHero then return end

	for i = 1, CombatDefine.COMBAT_HERO_CNT do
		local uuid = combatHero[i]
        local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid)
        if heroGrid then
		   if isHeroDot(human, heroGrid) then
		   	return true
		   end
           
           if HeroBook.isDot(human) == 1 then
               return true
           end
        end
	end
end

-- 某个伙伴是否有红点
function isHeroDot(human, heroGrid)
	if not heroGrid then return end

    if human.db.lv < 9 then
       return false
    end

	-- 装备
	if HeroEquip.isEquipDot(human, heroGrid) then
		return true
	end

    if FuwenLogic.isFuwenDot(human, heroGrid) then
		return true
	end

	-- 升级/进阶
	if isHeroLevelDot(human, heroGrid) and 
		not XingYaoGongMing.isGongMing(human,heroIndex)  then
		return true
	end

    --
    if isHeroJuexingDot(human, heroGrid.bagIndex, heroGrid) then
       return true
    end

	if BingshuLogic.isBingShuDot(human, heroGrid) then
		return
	end

end

-- 升级判定
function isHeroLvDot(human, heroGrid)
    if human.db.lv < 9 then
       return false
    end

    local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

	local lv = heroGrid and heroGrid.lv or 1
	local star = heroConfig and heroConfig.star or 0
	local quality = heroGrid and heroGrid.quality or 0
	local maxLv = HeroGrid.getMaxLv(heroGrid.star, quality)

	if lv < maxLv then -- 升级
		local conf = UpNeedExcel.upLv[lv + 1]
		if not conf then return end
		if human.db.jinbi < conf.money then return end
		if BagLogic.getItemCnt(human, ItemDefine.ITEM_GREEN_EXP_ID) < conf.soul then
			return 
		end
		return true
	end
end


-- 进阶判断
function isHeroUpDot(human, heroGrid)
    if human.db.lv < 9 then
       return false
    end

    local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

	local lv = heroGrid and heroGrid.lv or 1
	local star = heroGrid and heroGrid.star or 0
	local quality = heroGrid and heroGrid.quality or 0
	
	-- 进阶
	local maxQuality = HeroGrid.getMaxQuality(star)
	if quality >= maxQuality then
		return
	end

	local maxLv = HeroGrid.getMaxLv(heroGrid.star, maxQuality)	
	if lv < maxLv then
		return
	end

	local conf = UpNeedExcel.upQuality[quality + 1]
	if not conf then return end
	if human.db.jinbi < conf.money then return end
	if BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID) < conf.jinjieshi then
		return 
	end 

	return true
end

-- 升级/进阶判断
function isHeroLevelDot(human, heroGrid)
    if human.db.lv < 9 then
       return false
    end

	if isHeroLvDot(human, heroGrid) then -- 升级
		return true
	end

	if isHeroUpDot(human, heroGrid) then -- 进阶判断
		return true
	end

end



-- 升星/觉醒红点
function isHeroJuexingDot(human, heroIndex, heroGrid)
    if human.db.lv < 9 then
       return
    end

	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

    local attrConfig = HeroDefine.getAttrConfig(heroGrid.id, heroGrid.star)
    if not attrConfig then return end

	local nextAttrConfig = HeroDefine.getNextAttrConfig(heroGrid.id, heroGrid.star)
	if not nextAttrConfig then 
       return sendHeroJueXingMax(human, heroGrid.id, heroIndex)
    end

	-- 角色等级/世界等级是否可以
	local isFix = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then return end
	-- 判断消耗材料
    local needItemCnt = attrConfig.jinjieshi
	if BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID) < needItemCnt then
		return 
	end
	-- 额外材料
	for i = 1, #attrConfig.needItems do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		if BagLogic.getItemCnt(human, itemID) < itemCnt then
			return
		end
	end

	local without = {}
	without[heroIndex] = true
	for _, cond in ipairs(attrConfig.cond) do
		local ctype = cond[1] 
		local needCnt = cond[3] 
		if not needCnt then return end
		if ctype == HechengLogic.COND_TYPE_CAMPSTAR then
			needCnt = cond[4]
		end
		for i = 1, needCnt do
			local index = selectJuexingGrid(human, ctype, cond, without) 
			if not index then return end
			without[index] = true
		end
	end
	return true
end

-- 查找升星材料
function selectJuexingGrid(human, ctype, cond, without)
    for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 and not without[index] and 
			isFixJuexingCond(heroGrid, ctype, cond) then
			return index
		end
	end
end

-- 是否满足材料需求
function isFixJuexingCond(grid, ctype, cond)
	local heroConfig = HeroExcel.hero[grid.id]
	if not heroConfig then return end
	if ctype == HechengLogic.COND_TYPE_HEROID then
        local needConfig = HeroExcel.hero[cond[2]]
        if not needConfig then return end

        local needStar = cond[4] or needConfig.star
		if grid.id == cond[2] and needStar == grid.star then
		   return true
		end
	elseif ctype == HechengLogic.COND_TYPE_CAMPSTAR then
		if cond[2] ~= 0 and cond[2] ~= heroConfig.camp then
			return 
		end
		if cond[3] ~= grid.star then
			return
		end
		return true
	end
end

function sendBagDots(human)
	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
	local msgRet = Msg.gc.GC_HERO_BAG_DOTS
	msgRet.list[0] = 0
	for i = 1, CombatDefine.COMBAT_HERO_CNT do
		local uuid = combatHero and combatHero[i]
        local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid)
		if heroGrid then
			msgRet.list[0] = msgRet.list[0] + 1
			local net = msgRet.list[msgRet.list[0]] 
			net.bagIndex = heroGrid.bagIndex
			net.isDot = isHeroDot(human, heroGrid) and 1 or 0
		end
	end
	--Msg.trace(msgRet)
    msgRet.bookDot = HeroBook.isDot(human)
	Msg.send(msgRet, human.fd)
	refreshDot(human)
end

function refreshDot(human, uuid)
	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
	if not combatHero then return end

	local isFind = nil
	for i = 1, CombatDefine.COMBAT_HERO_CNT do
		if uuid == nil or combatHero[i] == uuid then
			isFind = true
			break
		end
	end
	if not isFind then return end
	RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_301)
end

-- 今日英雄重置剩余次数
function getResetLeftCnt(human)
	local heroResetCnt = human.db.heroResetCnt or 0
	return math.max(HERO_RESET_FREECNT - heroResetCnt, 0)
end

-- 重置返还材料
local RESET_RETURN_ITEMS = {}
function getResetReturnItems(heroGrid)
	Util.cleanTable(RESET_RETURN_ITEMS)

	-- 升级
	local lv = heroGrid.lv
	if heroGrid.oldLV then
		lv = heroGrid.oldLV
	end
	
	for i = 2, lv do
		local upcf = UpNeedExcel.upLv[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] or 0) + upcf.soul
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

	-- 升阶
	local quality = heroGrid.quality
	if heroGrid.oldQuality then
		quality = heroGrid.oldQuality
	end
	
	-- 升阶
	for i = 1, quality do
		local upcf = UpNeedExcel.upQuality[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + upcf.jinjieshi
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

    -- 升星材料
    for i = 1,heroGrid.star do
        local attrConfig = HeroDefine.getAttrConfig(heroGrid.id, i)
        if attrConfig then
			if  attrConfig.jinjieshi > 0 then RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + attrConfig.jinjieshi end
            for j = 1,#attrConfig.needItems do
                RESET_RETURN_ITEMS[attrConfig.needItems[j][1]] = (RESET_RETURN_ITEMS[attrConfig.needItems[j][1]] or 0) + attrConfig.needItems[j][2]
            end
        end
    end
	-- 护符/水晶材料
	local maxCnt = 100 -- 防止死循环
	local equipID = heroGrid.equip and heroGrid.equip[ItemDefine.EQUIP_SUBTYPE_SHUIJIN]
	while equipID do
		maxCnt = maxCnt - 1
		if maxCnt < 0 then 
			assert() 
		end
		local eupcf = EquipExcel.shuijingUpNeed[equipID]
		if not eupcf then break end
		local preEquipID = eupcf.prevID
		equipID = preEquipID
		if preEquipID > 0 then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + eupcf.money
			RESET_RETURN_ITEMS[ItemDefine.ITEM_SHUIJING_UPLEVEL_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_SHUIJING_UPLEVEL_ID] or 0) + eupcf.jinghua
		end
	end

	return RESET_RETURN_ITEMS
end

function getRealResetReturnItems(heroGrid)
	Util.cleanTable(RESET_RETURN_ITEMS)

	-- 升级
	local lv = heroGrid.lv
	if heroGrid.oldLV then
		lv = heroGrid.oldLV
	end
	
	for i = 2, lv do
		local upcf = UpNeedExcel.upLv[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] or 0) + upcf.soul
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

	-- 升阶
	local quality = heroGrid.quality
	if heroGrid.oldQuality then
		quality = heroGrid.oldQuality
	end
	
	-- 升阶
	for i = 1, quality do
		local upcf = UpNeedExcel.upQuality[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + upcf.jinjieshi
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

	return RESET_RETURN_ITEMS
end

-- 重置花费
function getResetNeedZuanshi(lv)
	if lv > 100 then
		return 50
	end
	return 0
end

-- 重置查询
function resetHeroQuery(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

	if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_RESET) then
		return
	end
	
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end
	if heroConfig.star > HERO_RESET_MAXSTAR then
		return Broadcast.sendErr(human, Util.format(Lang.HERO_RESET_ERR_STAR, HERO_RESET_MAXSTAR + 1))
	end

	ObjHuman.updateDaily(human)
	--[[if getResetLeftCnt(human) < 1 then
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_CNT)
	end--]]

	local list = getRealResetReturnItems(heroGrid)
	local msgRet = Msg.gc.GC_HERO_RESET_QUERY
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	msgRet.needZuanshi = getResetNeedZuanshi(heroGrid.lv)
	msgRet.maxFreeCnt = HERO_RESET_FREECNT
	msgRet.leftFreeCnt = getResetLeftCnt(human)
	msgRet.items[0] = 0
	for itemID, itemCnt in pairs(list) do
		if msgRet.items[0] >= #msgRet.items then
			break
		end
		msgRet.items[0] = msgRet.items[0] + 1
		Grid.makeItem(msgRet.items[msgRet.items[0]], itemID, itemCnt)
	end
	if msgRet.items[0] < 1 then
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_NONE)
	end
--	Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 英雄重置
function resetHero(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

	if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_RESET) then
		return
	end
	
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end
	if heroConfig.star > HERO_RESET_MAXSTAR then
		return Broadcast.sendErr(human, Util.format(Lang.HERO_RESET_ERR_STAR, HERO_RESET_MAXSTAR + 1))
	end

	local list = getRealResetReturnItems(heroGrid)
	if not next(list) then 
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_NONE)
	end

	if getResetLeftCnt(human) < 1 then
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_CNT)
	end

	local needZuanshi = getResetNeedZuanshi(heroGrid.lv)
	if not ObjHuman.checkRMB(human, needZuanshi) then
		return
	end
	ObjHuman.decZuanshi(human, -needZuanshi, "hero_reset")
	human.db.heroResetCnt = (human.db.heroResetCnt or 0) + 1

	heroGrid.lv = 1
	heroGrid.quality = 0
	if heroGrid.equip and heroGrid.equip[ItemDefine.EQUIP_SUBTYPE_SHUIJIN] then
		heroGrid.equip[ItemDefine.EQUIP_SUBTYPE_SHUIJIN] = nil 
		heroGrid.shuijingAttrID = nil
	end

	for itemID, itemCnt in pairs(list) do
		BagLogic.addItem(human, itemID, itemCnt, "hero_reset")
	end
	HeroEquip.putOffQuick(human, heroID, heroIndex, true)
	FuwenLogic.putOffQuick(human, heroID, heroIndex, true)
	XingYaoGongMing.onDelHero(human,heroGrid,heroIndex)
    heroGrid.fuwen = nil
    ObjHuman.doCalcHero(human,heroIndex)
    sendHeroBagDynamic(human, heroID, heroIndex)
	refreshDot(human, heroGrid.uuid)

	local msgRet = Msg.gc.GC_HERO_RESET
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	msgRet.items[0] = 0 
	for itemID, itemCnt in pairs(list) do
		if msgRet.items[0] >= #msgRet.items then
			break
		end

		if not ItemDefine.isEquip(itemID) then
		   msgRet.items[0] = msgRet.items[0] + 1
		   Grid.makeItem(msgRet.items[msgRet.items[0]], itemID, itemCnt)
		end
	end
	msgRet.items[0] = EquipLogic.makeEquipItem(human, msgRet.items, msgRet.items[0])
	Msg.send(msgRet, human.fd)	

	checkChangeMaxZDL(human, heroGrid)
end
